﻿namespace UnityEditor
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;

    internal class DefaultTreeViewGUI : ITreeViewGUI
    {
        protected const float k_BaseIndent = 2f;
        protected const float k_DropBetweenHeight = 3f;
        protected const float k_FoldoutWidth = 12f;
        protected const float k_IconWidth = 14f;
        protected const float k_IndentWidth = 14f;
        protected const float k_LineHeight = 16f;
        protected Rect m_InsertionMarkerRect;
        private PingData m_Ping = new PingData();
        protected TreeView m_TreeView;
        protected static Styles s_Styles;

        public DefaultTreeViewGUI(TreeView treeView)
        {
            this.m_TreeView = treeView;
        }

        internal virtual void BeginCreateNewAsset(int instanceID, ProjectWindowUtil.EndAction endAction, string pathName, Texture2D icon, string resourceFile)
        {
            this.ClearRenameAndNewNodeState();
            this.GetCreateAssetUtility().BeginNewAssetCreation(instanceID, endAction, pathName, icon, resourceFile);
            this.SyncFakeNode();
            if (!this.GetRenameOverlay().BeginRename(this.GetCreateAssetUtility().originalName, instanceID, 0f))
            {
                Debug.LogError("Rename not started (when creating new asset)");
            }
        }

        public virtual void BeginPingNode(TreeView.Node node, float topPixelOfRow, float availableWidth)
        {
            if ((node != null) && (topPixelOfRow >= 0f))
            {
                this.m_Ping.m_TimeStart = Time.realtimeSinceStartup;
                this.m_Ping.m_Content = new GUIContent(node.displayName, this.GetIconForNode(node));
                this.m_Ping.m_PingStyle = s_Styles.ping;
                this.m_Ping.m_ContentTopLeft = new Vector2((2f + (14f * node.depth)) + 12f, topPixelOfRow);
                this.m_Ping.m_AvailableWidth = availableWidth;
                this.m_Ping.m_FontStyle = !node.displayName.Equals("Assets") ? s_Styles.ping.fontStyle : FontStyle.Bold;
                this.m_TreeView.Repaint();
            }
        }

        public virtual bool BeginRename(TreeView.Node node, float delay)
        {
            return this.GetRenameOverlay().BeginRename(node.displayName, node.instanceID, delay);
        }

        public virtual void BeginRowGUI()
        {
            this.InitStyles();
            this.m_InsertionMarkerRect.x = -1f;
            this.SyncFakeNode();
            this.DoRenameOverlay();
        }

        private Vector2 CalcRowWidth(TreeView.Node node)
        {
            s_Styles.content.text = node.displayName;
            s_Styles.lineStyle.padding.left = (int) ((2f + (node.depth * 14f)) + 12f);
            return s_Styles.lineStyle.CalcSize(s_Styles.content);
        }

        private void ClearRenameAndNewNodeState()
        {
            this.m_TreeView.m_Data.RemoveFakeNode();
            this.GetCreateAssetUtility().Clear();
            this.GetRenameOverlay().Clear();
        }

        private void DebugPrintToEditorLogRecursive(TreeView.Node node)
        {
            Console.WriteLine(new string(' ', node.depth * 3) + node.displayName);
            foreach (TreeView.Node node2 in node.children)
            {
                this.DebugPrintToEditorLogRecursive(node2);
            }
        }

        protected void DoNodeGUI(Rect rect, TreeView.Node node, bool selected, bool focused, bool useBoldFont)
        {
            EditorGUIUtility.SetIconSize(new Vector2(16f, 16f));
            float num = 2f + (node.depth * 14f);
            Rect position = rect;
            int nodeControlID = TreeView.GetNodeControlID(node);
            bool isHover = (this.m_TreeView.m_Dragging.GetDropTargetControlID() == nodeControlID) && this.m_TreeView.m_Data.CanBeParent(node);
            bool flag2 = this.IsRenaming(node.instanceID);
            bool flag3 = this.m_TreeView.m_Data.IsExpandable(node);
            if (flag2)
            {
                float num3 = (num + 12f) + 14f;
                this.GetRenameOverlay().editFieldRect = new Rect(rect.x + num3, rect.y, rect.width - num3, rect.height);
            }
            if (Event.current.type == EventType.Repaint)
            {
                s_Styles.content.text = node.displayName;
                Texture iconForNode = this.GetIconForNode(node);
                s_Styles.content.image = iconForNode;
                if (flag2)
                {
                    selected = false;
                    s_Styles.content.text = string.Empty;
                }
                GUIStyle style = !useBoldFont ? s_Styles.lineStyle : s_Styles.lineBoldStyle;
                style.padding.left = (int) (num + 12f);
                style.Draw(rect, s_Styles.content, isHover, isHover, selected, focused);
                if (this.m_TreeView.m_Dragging.GetRowMarkerControlID() == nodeControlID)
                {
                    this.m_InsertionMarkerRect = new Rect((rect.x + num) + 12f, rect.y, rect.width - num, rect.height);
                }
            }
            if (flag3)
            {
                position.x = num;
                position.width = 12f;
                EditorGUI.BeginChangeCheck();
                bool expand = GUI.Toggle(position, this.m_TreeView.m_Data.IsExpanded(node), GUIContent.none, s_Styles.foldout);
                if (EditorGUI.EndChangeCheck())
                {
                    if (Event.current.alt)
                    {
                        this.m_TreeView.m_Data.SetExpandedWithChildren(node, expand);
                    }
                    else
                    {
                        this.m_TreeView.m_Data.SetExpanded(node, expand);
                    }
                    if (expand)
                    {
                        this.m_TreeView.UserExpandedNode(node);
                    }
                }
            }
            EditorGUIUtility.SetIconSize(Vector2.zero);
        }

        public virtual void DoRenameOverlay()
        {
            if (this.GetRenameOverlay().IsRenaming() && !this.GetRenameOverlay().OnGUI())
            {
                this.EndRename();
            }
        }

        public virtual void EndPingNode()
        {
            this.m_Ping.m_TimeStart = -1f;
        }

        public virtual void EndRename()
        {
            if (this.GetRenameOverlay().HasKeyboardFocus())
            {
                this.m_TreeView.GrabKeyboardFocus();
            }
            this.RenameEnded();
            this.ClearRenameAndNewNodeState();
        }

        public virtual void EndRowGUI()
        {
            if ((this.m_InsertionMarkerRect.x >= 0f) && (Event.current.type == EventType.Repaint))
            {
                s_Styles.insertion.Draw(this.m_InsertionMarkerRect, false, false, false, false);
            }
            this.HandlePing();
        }

        public virtual float GetContentIndent(TreeView.Node node)
        {
            return ((2f + (node.depth * 14f)) + 12f);
        }

        protected CreateAssetUtility GetCreateAssetUtility()
        {
            return this.m_TreeView.m_State.m_CreateAssetUtility;
        }

        public virtual void GetFirstAndLastRowVisible(List<TreeView.Node> rows, float topPixel, float heightInPixels, out int firstRowVisible, out int lastRowVisible)
        {
            firstRowVisible = (int) Mathf.Floor(topPixel / 16f);
            lastRowVisible = firstRowVisible + ((int) Mathf.Ceil(heightInPixels / 16f));
            firstRowVisible = Mathf.Max(firstRowVisible, 0);
            lastRowVisible = Mathf.Min(lastRowVisible, rows.Count - 1);
        }

        public virtual float GetHeightOfLastRow()
        {
            return 16f;
        }

        protected virtual Texture GetIconForNode(TreeView.Node node)
        {
            if (node == null)
            {
                return null;
            }
            Texture icon = null;
            if (this.IsCreatingNewAsset(node.instanceID))
            {
                icon = this.GetCreateAssetUtility().icon;
            }
            if (icon == null)
            {
                icon = node.icon;
            }
            if ((icon == null) && (node.instanceID != 0))
            {
                icon = AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(node.instanceID));
            }
            return icon;
        }

        public virtual int GetNumRowsOnPageUpDown(TreeView.Node fromNode, bool pageUp, float heightOfTreeView)
        {
            return (int) Mathf.Floor(heightOfTreeView / 16f);
        }

        protected RenameOverlay GetRenameOverlay()
        {
            return this.m_TreeView.m_State.m_RenameOverlay;
        }

        public virtual float GetTopPixelOfRow(int row, List<TreeView.Node> rows)
        {
            return (row * 16f);
        }

        public virtual Vector2 GetTotalSize(List<TreeView.Node> rows)
        {
            this.InitStyles();
            return new Vector2(1f, rows.Count * 16f);
        }

        private void HandlePing()
        {
            this.m_Ping.HandlePing();
            if (this.m_Ping.isPinging)
            {
                this.m_TreeView.Repaint();
            }
        }

        private void InitStyles()
        {
            if (s_Styles == null)
            {
                s_Styles = new Styles();
            }
        }

        protected virtual bool IsCreatingNewAsset(int instanceID)
        {
            return (this.GetCreateAssetUtility().IsCreatingNewAsset() && this.IsRenaming(instanceID));
        }

        protected virtual bool IsRenaming(int instanceID)
        {
            return ((this.GetRenameOverlay().IsRenaming() && (this.GetRenameOverlay().userData == instanceID)) && !this.GetRenameOverlay().isWaitingForDelay);
        }

        public virtual Rect OnRowGUI(TreeView.Node node, int row, float rowWidth, bool selected, bool focused)
        {
            Rect rect = new Rect(0f, row * 16f, rowWidth, 16f);
            this.DoNodeGUI(rect, node, selected, focused, false);
            return rect;
        }

        protected virtual void RenameEnded()
        {
            string name = !string.IsNullOrEmpty(this.GetRenameOverlay().name) ? this.GetRenameOverlay().name : this.GetRenameOverlay().originalName;
            int userData = this.GetRenameOverlay().userData;
            bool flag = this.GetCreateAssetUtility().IsCreatingNewAsset();
            bool userAcceptedRename = this.GetRenameOverlay().userAcceptedRename;
            if (flag)
            {
                if (userAcceptedRename)
                {
                    this.GetCreateAssetUtility().EndNewAssetCreation(name);
                }
            }
            else if (userAcceptedRename)
            {
                ObjectNames.SetNameSmartWithInstanceID(userData, name);
            }
        }

        private void SyncFakeNode()
        {
            if (!this.m_TreeView.m_Data.HasFakeNode() && this.GetCreateAssetUtility().IsCreatingNewAsset())
            {
                int instanceID = AssetDatabase.LoadAssetAtPath(this.GetCreateAssetUtility().folder, typeof(UnityEngine.Object)).GetInstanceID();
                this.m_TreeView.m_Data.InsertFakeNode(this.GetCreateAssetUtility().instanceID, instanceID, this.GetCreateAssetUtility().originalName, this.GetCreateAssetUtility().icon);
            }
            if (this.m_TreeView.m_Data.HasFakeNode() && !this.GetCreateAssetUtility().IsCreatingNewAsset())
            {
                this.m_TreeView.m_Data.RemoveFakeNode();
            }
        }

        internal class Styles
        {
            public GUIContent content = new GUIContent(EditorGUIUtility.FindTexture(EditorResourcesUtility.folderIconName));
            public GUIStyle foldout = "IN Foldout";
            public GUIStyle insertion = "PR Insertion";
            public GUIStyle label = "PR Label";
            public GUIStyle lineBoldStyle = new GUIStyle("PR Label");
            public GUIStyle lineStyle = new GUIStyle("PR Label");
            public GUIStyle ping = new GUIStyle("PR Ping");
            public GUIStyle toolbarButton = "ToolbarButton";

            public Styles()
            {
                this.lineBoldStyle.font = EditorStyles.boldLabel.font;
                this.lineBoldStyle.fontStyle = EditorStyles.boldLabel.fontStyle;
                this.ping.padding.left = 0x10;
                this.ping.fixedHeight = 16f;
            }
        }
    }
}

